/*
Copyright (C) 2009-2010 Xanadu Development Team

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "Acceptor.h"
#include <iostream>
#include "PacketHandler.h"
hash_map <int, int> Acceptor::ports;

Acceptor::Acceptor(int port, Selector* selector, AbstractPlayerFactory* apf) {
	abstractPlayerFactory = apf;
	SOCKET acceptSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (acceptSocket == INVALID_SOCKET) {
		cout << "socket error: " << WSAGetLastError();
		WSACleanup();
		cin.get();
		exit(1);
	}
	sockaddr_in service;
	service.sin_family = AF_INET;
	service.sin_addr.s_addr = INADDR_ANY;
	service.sin_port = htons(port);
	if (bind(acceptSocket, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR) {
		cout << "bind() error: " << WSAGetLastError();
		closesocket(acceptSocket);
		WSACleanup();
		cin.get();
		exit(1);
	}
	if (listen(acceptSocket, 10) == SOCKET_ERROR) {
		cout << "listen() error: " << WSAGetLastError();
		closesocket(acceptSocket);
		WSACleanup();
		cin.get();
		exit(1);
	}
	selector->registerSocket(acceptSocket, true, false, true, this);
	ports[acceptSocket] = port;
}

int Acceptor::handle(Selector* selector, int socket) {
	sockaddr_in cli_addr;
	int cli_len = sizeof(cli_addr);
	SOCKET sock = accept(socket, (struct sockaddr *) &cli_addr, &cli_len);
	if(sock == INVALID_SOCKET) {
		cout << "error accepting connection: " << WSAGetLastError() << endl;
		closesocket(sock);
		WSACleanup();
		cin.get();
		exit(1);
	}
	char IP[50];
	sprintf_s(IP, 20, "%d.%d.%d.%d", cli_addr.sin_addr.S_un.S_un_b.s_b1, cli_addr.sin_addr.S_un.S_un_b.s_b2, cli_addr.sin_addr.S_un.S_un_b.s_b3, cli_addr.sin_addr.S_un.S_un_b.s_b4);
	cout << "IP connected: " << IP << endl;
	AbstractPlayer* player = abstractPlayerFactory->createPlayer(ports[socket]);
	player->setIP(string(IP));
	PacketHandler* ph = new PacketHandlerMaple(sock, player);
	player->setPacketHandler(ph);
	selector->registerSocket(sock, true, false, true, ph);
	return 0;
}